package com.cloud.clouduser.security.common.filters;

import com.cloud.cloudcommons.Redis.SessionConsistance;
import com.cloud.cloudcommons.utils.CommonCheck;
import com.cloud.clouduser.security.base.code.imagecode.ImageCode;
import com.cloud.clouduser.security.common.exception.ValidateCodeException;
import com.cloud.clouduser.security.common.resulthandler.CommonAuthenticationFailureHandler;
import com.netflix.discovery.converters.Auto;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import com.cloud.clouduser.security.base.SecurityPorperties;
import org.springframework.boot.CommandLineRunner;
import org.springframework.social.connect.web.HttpSessionSessionStrategy;
import org.springframework.social.connect.web.SessionStrategy;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.UrlPathHelper;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Aurher: QiaoHang
 * @Description:
 * @Data: 2019/9/26 10:29
 * @Modified By:
 */
@Component
public class CommonImageCodeValidateFilter extends OncePerRequestFilter implements CommandLineRunner {

    SessionStrategy sessionStrategy = new HttpSessionSessionStrategy();
    AntPathMatcher pathMatcher = new AntPathMatcher();
    private Set<String> limitedUrls = new HashSet<>();
    @Autowired
    CommonAuthenticationFailureHandler commonAuthenticationFailureHandler;
    @Autowired
    SecurityPorperties securityPorperties;

    //加载受验证码限制的访问路径
    @Override
    public void run(String... args) throws Exception {
        String validatePath = securityPorperties.getValidate().getImage().getValidatePath();
        String[] strings = StringUtils.splitByWholeSeparatorPreserveAllTokens(validatePath, ",");
        Set<String> collect = Arrays.stream(strings).collect(Collectors.toSet());
        limitedUrls = collect;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain chain) throws ServletException, IOException {
        boolean flag = false;
        //当前请求的url需不需要被拦截
        String uri = request.getRequestURI();
        for (String limitedUrl : limitedUrls) {
            if(pathMatcher.match(limitedUrl,uri)){
                flag = true;
                break;
            }
        }
        if(flag){
            try {
                //校验验证码
                validate(request);
                System.out.println("验证码验证通过！");
            }catch (ValidateCodeException e){
                commonAuthenticationFailureHandler.onAuthenticationFailure(request,response,e);
                return;
            }
        }
        //继续以下过滤链
        chain.doFilter(request,response);
    }

    //校验验证码
    private void validate(HttpServletRequest request) {
        //获取session中的验证码
        Object attribute = sessionStrategy.getAttribute(new ServletWebRequest(request), SessionConsistance.SESSION_IMAGE_CODE);
        //获取session中验证码
        if(attribute==null)
            throw new ValidateCodeException("session中不存在验证码，违规登录！");
        ImageCode imageCode = (ImageCode) attribute;
        //获取请求中验证码
        String validateCode = request.getParameter("validateCode");
        if(CommonCheck.nullStrings(validateCode))
            throw new ValidateCodeException("request请求中不存在验证码，请输入验证码后重试！");
        //判断验证码是否过期
        if(imageCode.isExpired())
            throw new ValidateCodeException("验证码已过期，刷新页面重新获取！");
        //校验验证码
        if(!imageCode.getCode().equalsIgnoreCase(validateCode))
            throw new ValidateCodeException("验证码输入不正确！");
    }

}
